﻿namespace Socket.Core
{
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Runtime.CompilerServices;
    using System.Threading;

    public class TcpSession : AbstractSession
    {
        private readonly object _lockRelease;
        private Socket _mSocket;
        private readonly string _mToString;
        private bool _released;

        public TcpSession(SocketAsyncEventArgs token) : base(token)
        {
            this._lockRelease = new object();
            token.UserToken = this.UserToken;
            this._mSocket = token.AcceptSocket;
            this.RemoteIp = ((IPEndPoint) this._mSocket.RemoteEndPoint).Address.ToString();
            this.RemoteEndPoint = this._mSocket.RemoteEndPoint.ToString();
            this._mToString = this._mSocket.RemoteEndPoint.ToString();
        }

        private void Close()
        {
            try
            {
                TcpSession session = this;
                lock (session)
                {
                    if (this._mSocket != null)
                    {
                        this._mSocket.Close();
                        this._mSocket = null;
                    }
                }
            }
            catch (Exception)
            {
            }
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            this.Close();
        }

        ~TcpSession()
        {
            this.Dispose(false);
        }

        public override void Release()
        {
            object obj2 = this._lockRelease;
            lock (obj2)
            {
                if (!this._released)
                {
                    this.Close();
                    Thread.Sleep(100);
                    base.Release();
                    this._released = true;
                }
            }
        }
		private void SendCommand(byte[] buffer )  
		{  
			if (_mSocket != null && _mSocket.Connected)  
			{  
				SocketAsyncEventArgs sendArg = new SocketAsyncEventArgs();  
				
				sendArg.SetBuffer(buffer, 0, buffer.Length);  
				// 发送完成后的回调   
				sendArg.Completed += (objSender, mArg) =>  
				{  
					// 如果操作成功   
					if (mArg.SocketError == SocketError.Success)  
					{  
						//UnityEngine.Debug.Log("SendCommand成功.");
						// Dispatcher.BeginInvoke(() => txtbInfo.Text = "发送成功。");  
					}  
					else  
					{  
						UnityEngine.Debug.Log("SendCommand发送失败.");
						/*
	                            Dispatcher.BeginInvoke(() =>  
	                            {  
		                           //         this.txtbInfo.Text = "发送失败，错误：" + mArg.SocketError.ToString();  
		                        });  
		                        */
					}  
					// 报告异步操作结束   
					// MyEvent.Set();  
				};  
				// 重置信号   
				//    MyEvent.Reset();  
				
				// 异步发送   
				_mSocket.SendAsync(sendArg);  
				// 等待操作完成   
				//   MyEvent.WaitOne(6000);  
			}  
			
		}  

        public override bool Send(IMessage command)
        {
            try
            {
                byte[] sendBytes = command.GetSendBytes();
				SendCommand(sendBytes);
				//this._mSocket.SendAsync(sendBytes);
                //this._mSocket.BeginSend(sendBytes, 0, sendBytes.Length, 0, new AsyncCallback(this.SendCallback), this._mSocket);
            }
            catch (Exception)
            {
				UnityEngine.Debug.Log("Send Exception.");
                return false;
            }
            return true;
        }

        private void SendCallback(IAsyncResult iar)
        {
            try
            {
                Socket asyncState = (Socket) iar.AsyncState;
                if ((asyncState != null) && asyncState.Connected)
                {
                    //int num = asyncState.EndSendTo(iar);
                }
            }
            catch (Exception e)
            {
				UnityEngine.Debug.Log("SendCallback Exception.");
                UnityEngine.Debug.LogError(e.Message);
            }
        }

        public override string ToString()
        {
            return this._mToString;
        }

        public override bool IsConnected
        {
            get
            {
                return ((this._mSocket != null) && this._mSocket.Connected);
            }
        }

        public sealed override string RemoteEndPoint { get; protected set; }

        public sealed override string RemoteIp { get; protected set; }
    }
}

